package com.mainbo.core.shiro;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mainbo.core.vo.Result;
import com.mainbo.platform.http.HttpGetConnectionHelper;
import com.mainbo.platform.uc.client.JwtToken;
import com.mainbo.platform.uc.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author xww
 * @Description //TODO
 * @Date 2020/3/16   10:51
 **/
public class ShiroCasUserRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(com.mainbo.platform.uc.client.ShiroCasUserRealm.class);

    /**
     * 远程登录验证
     */
    private String remoteLoginUrl;

    /**
     * 连接超时，默认10分钟
     */
    private Integer connectTimeout = 600000;

    private Integer socketTimeout = 600000;

    private String appKey;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        JwtToken jwttoken = (JwtToken) token;
        if (jwttoken.getPrincipal() == null) {
            Map<String, String> paramMap = new HashMap<String, String>();
            paramMap.put("username", jwttoken.getUsername());
            paramMap.put("password", new String(jwttoken.getPassword()));
            paramMap.put(JwtUtils.APP_KEY, appKey);
            try {
                String rs = HttpGetConnectionHelper.post(remoteLoginUrl, paramMap, connectTimeout, socketTimeout);
                Result result = JSON.parseObject(rs, Result.class);
                if (result != null && Result.SUCCESS.equals(result.getCode())) { // 登录成功
                    JSONObject info = (JSONObject) result.getData();
                    Claims clms = JwtUtils.decodeToken(info.getString(JwtUtils.JWT_PARA_NAME));
                    JwtToken newjwttoken = new JwtToken(clms.getSubject(), clms);
                    newjwttoken.setPassword(jwttoken.getPassword());
                    jwttoken.setJwt(info.getString(JwtUtils.JWT_PARA_NAME));
                    jwttoken.setPrincipal(clms.getSubject());
                    jwttoken.setInfos(clms);
                    jwttoken = newjwttoken;
                } else {
                    logger.info("remote login failed, message:{}", result != null ? result.getMsg() : "result is null");
                    throw new AuthenticationException(result != null ? result.getMsg() : "result is null");
                }
            } catch (Exception e) {
                logger.warn("login failed", e);
                throw new AuthenticationException("login failed");
            }
        }

        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(jwttoken.getPrincipal(), jwttoken.getPassword(),
                getName());
        return info;
    }

    /**
     * Getter method for property <tt>remoteLoginUrl</tt>.
     *
     * @return property value of remoteLoginUrl
     */
    public String getRemoteLoginUrl() {
        return remoteLoginUrl;
    }

    /**
     * Setter method for property <tt>remoteLoginUrl</tt>.
     *
     * @param remoteLoginUrl
     *          value to be assigned to property remoteLoginUrl
     */
    public void setRemoteLoginUrl(String remoteLoginUrl) {
        this.remoteLoginUrl = remoteLoginUrl;
    }

    /**
     * Getter method for property <tt>connectTimeout</tt>.
     *
     * @return property value of connectTimeout
     */
    public Integer getConnectTimeout() {
        return connectTimeout;
    }

    /**
     * Setter method for property <tt>connectTimeout</tt>.
     *
     * @param connectTimeout
     *          value to be assigned to property connectTimeout
     */
    public void setConnectTimeout(Integer connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    /**
     * Getter method for property <tt>socketTimeout</tt>.
     *
     * @return property value of socketTimeout
     */
    public Integer getSocketTimeout() {
        return socketTimeout;
    }

    /**
     * Setter method for property <tt>socketTimeout</tt>.
     *
     * @param socketTimeout
     *          value to be assigned to property socketTimeout
     */
    public void setSocketTimeout(Integer socketTimeout) {
        this.socketTimeout = socketTimeout;
    }

    /**
     * Getter method for property <tt>appKey</tt>.
     *
     * @return property value of appKey
     */
    public String getAppKey() {
        return appKey;
    }

    /**
     * Setter method for property <tt>appKey</tt>.
     *
     * @param appKey
     *          value to be assigned to property appKey
     */
    public void setAppKey(String appKey) {
        this.appKey = appKey;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return new SimpleAuthorizationInfo();
    }

}
